package org.campuscontent.util;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Arrays;

import org.campuscontent.config.Config;
import org.campuscontent.model.AbstractGraph;
import org.campuscontent.model.AutomataCellViewFactory;
import org.campuscontent.model.Transition;
import org.campuscontent.ui.AutomataGraph;
import org.jgraph.graph.DefaultGraphCell;
import org.jgraph.graph.GraphModel;

public class GraphInspector
{

    GraphModel currentModel;

    ArrayList<String> start_state;
    ArrayList<String> end_state;

    ArrayList<String> all_state;
    ArrayList<Transition> transition_list;
    
    ArrayList<String> operatorSet	= new ArrayList<String>(Arrays.asList("|","*",","));
    
    DefaultGraphCell currentCell;
    AutomataGraph graph;

    public GraphInspector(
    		AutomataGraph graph)
    {
    	this.graph		=	graph;
        currentModel 	= 	graph.getModel();

        start_state = new ArrayList<String>();
        end_state 	= new ArrayList();

        all_state 	= new ArrayList();

        transition_list = new ArrayList();

        update();
        // update();
    }
    
    public boolean nextHighlight(String input)
    {
    	int cellCount = currentModel.getRootCount();
    	
    	DefaultGraphCell cell;
    	
    	for(int i = 0; i < cellCount; i++)
    	{
    		cell	=	(DefaultGraphCell) currentModel.getRootAt( i );
    		
    		if ( currentModel.isEdge( cell ) )
    		{
    			Object source = currentModel.getParent( currentModel.getSource( cell ) );
    			Object target = currentModel.getParent( currentModel.getTarget( cell ) );
    		
    			if(currentCell.toString().equals(source.toString()) && removeSeparator(cell.toString()).equals(input))
    			{
    				graph.setNodeColor(AutomataCellViewFactory.getID(currentCell), Color.green);
    				graph.setLinkColor(AutomataCellViewFactory.getID((DefaultGraphCell)source), AutomataCellViewFactory.getID((DefaultGraphCell)target), Color.green);
    				
    				currentCell	= (DefaultGraphCell)target;
    				return true;
    			}
    		}
    	}
    	return false;
    }
    
    public String getRefStr()
    {
    	String 	current, next;
    	
    	current		=	start_state.get(0);
    	
    	return getNext(current,"", 1);
    }
    
    public String getNext(String source, String current, int depth)
    {
    	
    	ArrayList<Transition>	connection;
    	ArrayList<String>		tempResult	= new ArrayList<String>();
    	ArrayList<String>		finalResult	= new ArrayList<String>();
    	
    	connection	= getOutConnections(source, transition_list);
    	
    	for(int i = 0; i < connection.size(); i++)
    	{
    		if(depth >= 5 && end_state.contains(connection.get(i).getTarget()))
    		{
    			return current+","+removeSeparator(connection.get(i).getConnection());
    		}
    		else if(depth == 1)
    		{
    			return getNext(connection.get(i).getTarget(),current+removeSeparator(connection.get(i).getConnection()), depth+1);
    		}
    		else if(depth < 15)
    		{
      			return getNext(connection.get(i).getTarget(),current+","+removeSeparator(connection.get(i).getConnection()), depth+1);
    		}
    	}
    	
    	return null;
    }
    
    
    
    public boolean previousHighlight(String input)
    {
    	int cellCount = currentModel.getRootCount();
    	
    	DefaultGraphCell cell;
    	
    	for(int i = 0; i < cellCount; i++)
    	{
    		cell	=	(DefaultGraphCell) currentModel.getRootAt( i );
    		
    		if ( currentModel.isEdge( cell ) )
    		{
    			Object source = currentModel.getParent( currentModel.getSource( cell ) );
    			Object target = currentModel.getParent( currentModel.getTarget( cell ) );
    		
    			if(currentCell.toString().equals(target.toString()) && removeSeparator(cell.toString()).equals(input))
    			{
    				graph.setNodeColor(AutomataCellViewFactory.getID((DefaultGraphCell)source), Color.black);
    				graph.setLinkColor(AutomataCellViewFactory.getID((DefaultGraphCell)source), AutomataCellViewFactory.getID((DefaultGraphCell)target), Color.black);
    				
    				currentCell	= (DefaultGraphCell)source;
    				return true;
    			}
    		}
    	}
    	return false;
    }
    
    public boolean isEndState()
    {
    	if( AutomataCellViewFactory.getNodeType( currentCell ).toString().equals( "END" ) ) 
    		return true;
    	else
    		return false;
    }

    public ArrayList getCellLabels(String cellType )
    {

        ArrayList cellLabelList = new ArrayList();

        if ( cellType.equals( "start" ) )
        {
            return start_state;
        }
        else if ( cellType.equals( "end" ) )
        {
            return end_state;
        }
        else if ( cellType.equals( "node" ) )
        {
            return all_state;
        }
        else if ( cellType.equals( "edge" ) )
        {
            Transition currentTransition;
            for ( int i = 0; i < transition_list.size(); i++ )
            {
                currentTransition = (Transition) transition_list.get( i );
                cellLabelList.add( currentTransition.getConnection().trim() );
            }
        }
        else if ( cellType.equals( "transition" ) )
        {
            Transition currentTransition;
            for ( int i = 0; i < transition_list.size(); i++ )
            {

                currentTransition = (Transition) transition_list.get( i );

                cellLabelList.add( "((" + currentTransition.getSource().toString().trim() + "," + currentTransition.getConnection().toString().trim() + "), "
                + currentTransition.getTarget().toString().trim() + ")" );

            }

        }

        return cellLabelList;

    }
    
    public String validate()
    {
    	if(start_state.size()==0)
    	{
    		return "Please set at least one \"Start\" node";
    	} 
    	else if (end_state.size()==0)
    	{
    		return "Please set at least one \"End\" node";
    	}
    	
    	int cellCount 	= currentModel.getRootCount();
    	int edgeCnt		= 0;

        for ( int i = 0; i < cellCount; i++ )
        {

            DefaultGraphCell cell = (DefaultGraphCell) currentModel.getRootAt( i );

            if ( currentModel.isEdge( cell ) )
            	edgeCnt++;
        }
        
        if(edgeCnt==0)
        	return "Please draw at least one edge!";
        
    	return "valid";
    }


    public String getRExpression()
    {
        String rExpression = "";
        int i, j, k;

        ArrayList<Transition> inConnection	= new ArrayList<Transition>();
        ArrayList<Transition> outConnection	= new ArrayList<Transition>();
        
        ArrayList<Transition> temp_transition_list;
     
        
        String currentState, currentStart, currentEnd;
        
        String left, middle, right, exist, update;
        
        ArrayList<String> partRExpression	= new ArrayList<String>();

        for (int endStateCnt = 0; endStateCnt < end_state.size(); endStateCnt++)
        {
        	temp_transition_list	= new ArrayList<Transition>(transition_list);
        	
        	currentEnd	= end_state.get(endStateCnt);
        	
        	for ( i = 0; i < all_state.size(); i++ )
            {

                 // get the current state
                 currentState = (String) all_state.get( i );
                 
                 // get the self loop string
                 middle = removeSeparator(getSelfConnection(currentState));
                 
                 // get all the in and out connections to state i 
                 inConnection 	= getInConnections	(currentState,	temp_transition_list);
                 outConnection	= getOutConnections	(currentState,	temp_transition_list);           
                 
                 if(isSState(currentState)||(isEState(currentState)&&currentState.equals(currentEnd)))
                 	continue;
                 
                 for ( j = 0; j < inConnection.size(); j++ )
                 	for ( k = 0; k < outConnection.size(); k++)
                 	{
                 		//get the exist connection
                         exist	= 	removeSeparator(getConnection(inConnection.get(j).getSource(), outConnection.get(k).getTarget(), temp_transition_list));
                         
                 		left		= removeSeparator(inConnection		.get(j)	.getConnection());
                 		right		= removeSeparator(outConnection		.get(k)	.getConnection());
                 		
                 		
                 		if(middle.equals(""))
                 			update 	= 	"("	+	left	+	","	+	right	+	")";
                 		else
                 			update	=	"("	+	left 	+ 	","	+	middle	+	"*"	+	","	+	right	+ ")";
                 		
                 		if(!exist.equals(""))
                 		{
                 			update	= "("	+	exist	+ 	")"	+	"|"	+	"("	+	update	+	")";
                 			int existEdge	= getConnectionID(inConnection.get(j).getSource(), outConnection.get(k).getTarget(), temp_transition_list);
                 			temp_transition_list.remove(existEdge);                 			
                 		}
                 	
                 			
                 		temp_transition_list.add(new Transition(inConnection.get(j).getSource(), outConnection.get(k).getTarget(), update));
                 	
                 		
                 		

                 	}
                 
                 removeState(currentState, temp_transition_list);
            }
        	
        	//get the partly regular expression
        	currentStart	= start_state.get(0);
    		currentEnd		= end_state.get(endStateCnt);
    		
    		partRExpression.add(getPartExpression(currentStart, currentEnd, temp_transition_list));
        }

        for(i = 0; i < partRExpression.size(); i++)
        {
        	if(rExpression.equals(""))
        		rExpression = partRExpression.get(i);
        	else
        		rExpression = "(" + rExpression + ")" + "|" + "(" + partRExpression.get(i) + ")";
        }
        
        rExpression	= removeBrackets(rExpression);
        	
        return rExpression;
    }
    
    String removeBrackets(String rExpression)
    {
    	char[] newExpression					;
    	ArrayList<Integer>	currentBracket		= new ArrayList<Integer>();
    	ArrayList<Integer>	redundancyChar		= new ArrayList<Integer>();
    	
    	int bracketInd;
    	
    	ArrayList<Boolean>	currentRedundancy	= new ArrayList<Boolean>();
    	
    	String tempResult;
    	
    	for(int i = 0; i < rExpression.length(); i++)
    	{
    		if(rExpression.charAt(i)=='(')
    		{
    			currentBracket.add(i);
    			currentRedundancy.add(true);
    		}
    		else if(rExpression.charAt(i)==')')
    		{
    			bracketInd	= currentBracket.size()-1;
    			if(currentRedundancy.get(bracketInd))
    			{
    				redundancyChar.add(i);
    				redundancyChar.add(currentBracket.get(bracketInd));
    				currentBracket.remove(bracketInd);
    				currentRedundancy.remove(bracketInd);
    			}
    			else
    			{
    				currentBracket.remove(bracketInd);
    				currentRedundancy.remove(bracketInd);
    			}
    				
    		}else
    		{
    			if(currentBracket.size()>0)
    			{
    				bracketInd	= currentBracket.size()-1;
    				currentRedundancy.set(bracketInd, false);
    			}
    		}
    			
    	}
    	
    	int pointer	= 0;
    	int size	= rExpression.length()	- redundancyChar.size();
    	
    	newExpression	= new char[size];
    	
    	for(int i = 0; i < rExpression.length(); i++)
    	{
    		if(!redundancyChar.contains(i))
    		{
    			newExpression[pointer] = rExpression.charAt(i);
    			pointer++;
    		}
    	}
    		
    	
    	tempResult	=	new String(newExpression);
    	
    	
    	//Clear the result from last step
    	
    	currentBracket.clear();
    	redundancyChar.clear();
    	currentRedundancy.clear();
    	
    	//Further remove the redundant brackets;
    	for(int i = 0; i < tempResult.length(); i++)
    	{
    		//Catch the possible redundant brackets
    		if(tempResult.charAt(i)=='(')
    		{
    			currentBracket.add(i);
    			if(i==0||tempResult.charAt(i-1)!='|')
    				currentRedundancy.add(true);
    			else
    				currentRedundancy.add(false);
    		}
    		//See if the bracket is really redundant
    		else if(tempResult.charAt(i)==')')
    		{
    			bracketInd	= currentBracket.size()-1;
    			if(((i==tempResult.length()-1)||(tempResult.charAt(i+1)!='|'&&tempResult.charAt(i+1)!='*'))&&currentRedundancy.get(bracketInd)==true)
    			{
    				redundancyChar.add(currentBracket.get(bracketInd));
    				redundancyChar.add(i);
    			}
    			currentBracket.remove(bracketInd);
    			currentRedundancy.remove(bracketInd);
    		}
    	}
    	
    	//generate the final result as char array
    	pointer	= 0;
    	size	= tempResult.length()	- redundancyChar.size();
    	
    	newExpression	= new char[size];
    	
    	for(int i = 0; i < tempResult.length(); i++)
    	{
    		if(!redundancyChar.contains(i))
    		{
    			newExpression[pointer] = tempResult.charAt(i);
    			pointer++;
    		}
    	}   		
    
    	return new String(newExpression);
    }
    
    
    
    String getPartExpression(String source, String target, ArrayList<Transition> temp_list)
    {
    	String result; 	
    	
    	
    	String R1, R2, R3, R4;
    	
    	if(source.equals(target))
    		result	=  "("	+	removeSeparator(getConnection(source, target, temp_list))	+	")"	+	"*";
    	else
    	{
    		R1	= removeSeparator(getConnection(source, source, temp_list));
    		R2	= "("	+	removeSeparator(getConnection(source, target, temp_list))	+	")";
    		R3	= removeSeparator(getConnection(target, target, temp_list));
    		R4	= removeSeparator(getConnection(target, source, temp_list));
    		
    		if(!R1.equals(""))
    		{
    			R1	= "("	+	removeSeparator(getConnection(source, source, temp_list))	+	")";
    			
    			if(!R3.equals(""))
    			{
    				R3	= "("	+	removeSeparator(getConnection(target, target, temp_list))	+	")";
    				
    				if(!R4.equals(""))
    				{
    					R4	= "("	+	removeSeparator(getConnection(target, source, temp_list))	+	")";
    				
    					result = R1 + "*" + "," + R2 + "," + "(" + "(" + R3 + ")" + "|" + "(" + R4 + "," + R1 + "*" + "," + R2 + ")" + ")" + "*";
    				}
    				else
    					result = R1 + "*" + "," + R2 + "," +  R3 + "*";
    			}
    			else
    			{
    				if(!R4.equals(""))
    				{
    					R4	= "("	+	removeSeparator(getConnection(target, source, temp_list))	+	")";
    					result = R1 + "*" + "," + R2 + "," + "(" + R4 + "," + R1 + "*" + "," + R2 + ")"  + "*";
    				}
    				else
    					result = R1 + "*" + "," + R2;
    			}
    		}
    		else
    		{
    			if(!R3.equals(""))
    			{
    				R3	= "("	+	removeSeparator(getConnection(target, target, temp_list))	+	")";
    				
    				if(!R4.equals(""))
    				{
    					R4	= "("	+	removeSeparator(getConnection(target, source, temp_list))	+	")";
    					result = R2 + "," + "(" + "(" + R3 + ")" + "|" + "(" + R4 + "," + R2 + ")" + ")" + "*";
    				}
    				else
    					result = R2 + "," +  R3 + "*";
    			}
    			else
    			{
    				if(!R4.equals(""))
    				{
    					R4	= "("	+	removeSeparator(getConnection(target, source, temp_list))	+	")";
    					result = R2 + "," + "(" + R4 + "," + R2 + ")"  + "*";
    				}
    				else
    					result = R2;
    			}
    		}   		
    	}
    	return result;
    }
    
    String getConnection(String source, String target, ArrayList<Transition> search_list)
    {
    	
    	for ( int i = 0; i < search_list.size(); i++ )
        {

            Transition transition =  search_list.get( i );

            if ( transition.getSource().equals( source ) && transition.getTarget().equals( target ) ) 
            	return	transition.getConnection();
        }
    	
    	return "";
    }
    
    int getConnectionID(String source, String target, ArrayList<Transition> search_list)
    {
    	
    	for ( int i = 0; i < search_list.size(); i++ )
        {

            Transition transition =  search_list.get( i );

            if ( transition.getSource().equals( source ) && transition.getTarget().equals( target ) ) 
            	return	i;
        }
    	
    	return 0;
    }
    
    

	void removeState(String state,  ArrayList<Transition>  list)
	{
		ArrayList<Transition> connections	= getConnections(state, list);
		remove(list, connections);
	}

    private ArrayList<Transition> getConnections( String state, ArrayList<Transition> tranList )
    {

        ArrayList<Transition> subConnection = new ArrayList<Transition>();

        for ( int i = 0; i < tranList.size(); i++ )
        {

            Transition transition =  tranList.get( i );

            if ( transition.getSource().equals( state ) || transition.getTarget().equals( state ) ) 
            	subConnection.add( transition );
        }
        return subConnection;
    }

    private void remove( ArrayList<Transition> source, ArrayList<Transition> remove )
    {

        for ( int i = 0; i < remove.size(); i++ )
            if ( source.contains( remove.get( i ) ) ) source.remove( remove.get( i ) );

    }
    
    String getSelfConnection(String state)
    {
    	 for ( int i = 0; i < transition_list.size(); i++ )
         {

             Transition transition = transition_list.get( i );

             if ( transition.getTarget().equals( state ) && transition.getSource().equals(state) ) 
            	 return transition.getConnection();
         }
    	 
    	return "";
    }

    public void update()
    {

        int cellCount = currentModel.getRootCount();

        // String newTransition;

        start_state.clear();
        end_state.clear();

        all_state.clear();

        transition_list.clear();

        for ( int i = 0; i < cellCount; i++ )
        {

            DefaultGraphCell cell = (DefaultGraphCell) currentModel.getRootAt( i );

            if ( currentModel.isEdge( cell ) )
            {
                Object source = currentModel.getParent( currentModel.getSource( cell ) );
                Object target = currentModel.getParent( currentModel.getTarget( cell ) );
                // cellLabelList.add(new Transition(source.toString().trim(),
                // target
                // .toString().trim(), cell.toString().trim()));
                addTransition( new Transition( source.toString().trim(), target.toString().trim(), cell.toString().trim() ) );
            }
            else
            {
                addState( all_state, cell.toString().trim() );

                if ( AutomataCellViewFactory.getNodeType( cell ).toString().equals( "START" )||AutomataCellViewFactory.getNodeType( cell ).toString().equals( "STARTEND" ) ) 
                {
                	addState( start_state, cell.toString().trim() );
                	currentCell	= cell;
                }

                if ( AutomataCellViewFactory.getNodeType( cell ).toString().equals( "END" )||AutomataCellViewFactory.getNodeType( cell ).toString().equals( "STARTEND" ) ) 
                	addState( end_state, cell.toString().trim() );

            }
        }


    }

    public void addTransition( Transition newTransition )
    {
        if ( !transition_list.contains( newTransition ) ) transition_list.add( newTransition );
    }

    public void addState( ArrayList stateList, String state )
    {
        if ( !stateList.contains( state ) ) stateList.add( state );
    }

    public boolean hasIntersect( ArrayList listA, ArrayList listB )
    {

        boolean result = true;

        String currentState;

        if ( listA.size() == 0 ) result = false;
        else if ( listB.size() == 0 ) result = false;
        else
        {
            for ( int i = 0; i < listA.size(); i++ )
            {
                currentState = (String) listA.get( i );
                if ( listB.contains( currentState ) ) result = false;
            }
        }
        return result;
    }

    private ArrayList<Transition> getInConnections( String state, ArrayList<Transition> tranList )
    {

        ArrayList<Transition> subConnection = new ArrayList<Transition>();

        for ( int i = 0; i < tranList.size(); i++ )
        {

            Transition transition = tranList.get( i );

            if ( transition.getTarget().equals( state ) && !transition.getSource().equals( state ))
            	subConnection.add( transition );
        }
        return subConnection;
    }
    
    boolean isSState(String state)
    {
    	for(int i = 0; i < start_state.size(); i++)
    		if(state.equals(start_state.get(i)))
    				return true;
    	
    	return false;
    }
    
    boolean isEState(String state)
    {
    	for(int i = 0; i < end_state.size(); i++)
    		if(state.equals(end_state.get(i)))
    				return true;
    	
    	return false;
    }

    private ArrayList<Transition> getOutConnections( String state, ArrayList<Transition> tranList )
    {

        ArrayList<Transition> subConnection = new ArrayList<Transition>();

        for ( int i = 0; i < tranList.size(); i++ )
        {

            Transition transition = tranList.get( i );

            if ( transition.getSource().equals( state ) && !transition.getTarget().equals( state ) ) 
            	subConnection.add( transition );
        }
        return subConnection;
    }
    
    public void removeLabels()
    {
    	 int cellCount = currentModel.getRootCount();
    	 currentModel.beginUpdate();
    	 for ( int i = 0; i < cellCount; i++ )
         {
             DefaultGraphCell cell = (DefaultGraphCell) currentModel.getRootAt( i );
             cell.setUserObject("");        
         }
    	
    	 
              
    
    }
    
    public Queue parseRE(String rExpression)
    {
    	Queue	operand		= 	new Queue();
    	Stack	operator	=	new	Stack();
    	
    	int sPointer, cPointer;
    	
    	String cOperator, tOperator;
    	
    	sPointer = cPointer = 0;
    	
    	//read each character of the regular expression
    	while(sPointer<rExpression.length())
    	{
    		//whether the current character is an operand or an operator
    		while(cPointer<rExpression.length()&&validate(rExpression.charAt(cPointer)))
        	      		cPointer++;
        		
    		
    		//if the current substring is an operand
    		if(cPointer!=sPointer)
    		{
    			operand.insert(rExpression.substring(sPointer, cPointer));   
    			sPointer = cPointer;
    		}
    		//if the current substring is an operator
    		else
    		{
    			
    			cOperator	= rExpression.substring(sPointer, cPointer+1);
    			
    			if(cOperator.equals("("))
    			{
    				operator.push(cOperator);					
    			}
    			else if(cOperator.equals("*"))
    			{
    				operator.push(cOperator);
    			}
    			else if(cOperator.equals(",")||cOperator.equals("|") )
    			{
    				while((tOperator=operator.pop())!=null)
        			{
        					if(tOperator.equals("*"))
        					{
        						operand.insert(tOperator);
        					}
        					else 
        						break;        				
    				}
    				
    				if(tOperator!=null)
    				{
    					operator.push(tOperator);
    					operator.push(cOperator);    						
    				}
    				else
    					operator.push(cOperator);	
    				
    				
    			}
    			else if(cOperator.equals(")"))
    			{
    				while((tOperator=operator.pop())!=null && !tOperator.equals("("))
    				{
    					operand.insert(tOperator);
    				}
    			}
    			
    			sPointer = ++cPointer;		
    			
    		}
    		
    		
    	}
    	
    	//pop up the rest operators and insert them into operand queue
    	while((tOperator=operator.pop())!=null)
    		operand.insert(tOperator);
    	
    	return operand;
    	
    }
    
    @SuppressWarnings("unused")
    public AbstractGraph getGraphFromRe(String rExpression )
    {
        int sPointer, ePointer, cPointer;
    	
        
    	Queue	operand		= 	new Queue();
    	Stack	operator	=	new	Stack();
    	
    	String cOperator, tOperator;
    	
    	AbstractGraph	currentGraph, tempGraph;
    	
    	String cString;
    	String sNode, eNode;
    	
    	tempGraph 		= new AbstractGraph();
    	currentGraph	= new AbstractGraph();
    	    	
    	sPointer = ePointer = cPointer = 0;
    	
    	operand 	= parseRE(rExpression);
    	
    	currentGraph = getGraphFromPosfix(operand);
    	
    	return currentGraph;
    }
    
    public AbstractGraph getGraphFromPosfix(Queue operand)
    {
       	GraphStack	graphStack	=	new	GraphStack();
       	
       	AbstractGraph	currentGraph, tempGraph;
       	
       	currentGraph	= new AbstractGraph();
    	
    	String sNode, eNode;
    	
    	String cString;
    	
    	while((cString=operand.get())!=null)
    	{
    		if(isOperator(cString))
    		{
    			if(cString.equals("*"))
    			{
    				if((tempGraph=graphStack.pop())!=null)
    				{
    					currentGraph = tempGraph.addLoop();
    					graphStack.push(currentGraph);
    				}
    				else 
    					return null;
    			}
    			else if (cString.equals(","))
    			{
    				if(((currentGraph=graphStack.pop())!=null) && (tempGraph=graphStack.pop())!=null)
    				{
    					currentGraph	= tempGraph.combineGraph(currentGraph);
    					graphStack.push(currentGraph);
    				}
    				else 
    					return null;
    			}
    			else if(cString.equals("|"))
    			{
    				if(((tempGraph=graphStack.pop())!=null) && (currentGraph=graphStack.pop())!=null)
    				{
    					currentGraph	= tempGraph.joinGraph(currentGraph);
    					graphStack.push(currentGraph);
    				}
    				else 
    					return null;
    			}
    					
    		}
    		else
    		{
    			tempGraph 		= new AbstractGraph();
    			
    			sNode	= tempGraph.addNode(1);
    			eNode	= tempGraph.addNode(2);
    			
    			tempGraph.addEdge(cString, tempGraph.getNodeByLabel(sNode), tempGraph.getNodeByLabel(eNode));
    			
    			graphStack.push(tempGraph);
    		}
    	}
    	
    	currentGraph	= graphStack.pop().eliminateEmpty();
    	currentGraph.minimize();
    	
    	return currentGraph;
    	
    }
    
    boolean isOperator(String c)
    {
    	return operatorSet.contains(c);
    }
    
    boolean validate(char x)
    {
    	if(x>='a'&&x<='z')
    		return true;
    	else if(x>='A'&&x<='Z')
    		return true;
    	else if(x>='0'&&x<='9')
    		return true;
    	else if(x=='_'||x=='-'||x==' ')
     		return true;
    	
    	return false;
    }
    
    String removeSeparator(String originalStr)
    {
    	int index = originalStr.indexOf("//");
    	if(index!=-1)    	
    		return originalStr.substring(0, index).trim();
    	else 
    		return originalStr;
    }
    
    public ArrayList<Transition> getTransitionList()
	{
		return transition_list;
	}
    
    public String getTransitionListAsAllrows()
    {
    	String allRows="";
    	for ( int i = 0; i < transition_list.size(); i++ )
        {
    		Transition transition = transition_list.get( i );
    		String[] line = new String[3];
    		line[0]		 = transition.getSource();
    		line[1]  = removeSeparator(transition.getConnection());
    		line[2]			 = transition.getTarget();
    		String row = rowToString(line);
    		allRows = allRows +row + Config.ALLOC_TABLE_SPLITOR;
        }

    	return allRows;
    }
    
	public String rowToString(String[] comps) {
		String[] parts = { "((", ",", ")," };
		for (int i = 0; i < 3; i++) {
			parts[i] += comps[i];

		}
		String row = parts[0] + parts[1] + parts[2] + ")";
		return row;
	}

}

class Stack
{
	ArrayList<String> stack;
	
	public Stack()
	{
		stack = new ArrayList<String>();
	}
	
	public String pop()
	{
		int size = stack.size();
		
		if(size==0)
			return null;
		else
			return stack.remove(size-1);
		
	}
	
	public void push(String newItem)
	{
		stack.add(newItem);
	}
	
}

class GraphStack
{
	ArrayList<AbstractGraph> stack;
	
	public GraphStack()
	{
		stack = new ArrayList<AbstractGraph>();
	}
	
	public AbstractGraph pop()
	{
		int size = stack.size();
		
		if(size==0)
			return null;
		else
			return stack.remove(size-1);
		
	}
	
	public void push(AbstractGraph newItem)
	{
		stack.add(newItem);
	}
}

class Queue
{
	ArrayList<String> queue;
	
	public Queue()
	{
		queue = new ArrayList<String>();
	}
	
	public String get()
	{
		int size = queue.size();
		
		if(size==0)
			return null;
		else
			return queue.remove(0);
		
	}
	
	public void insert(String newItem)
	{
		queue.add(newItem);
	}
}
